﻿using System;
using System.Data;
using Ledict.ConditionExtract.Common;
using Ledict.Utility.Helper;
using Lucene.Net.Analysis.CJK;
using Lucene.Net.Documents;
using Lucene.Net.Index;
using Lucene.Net.QueryParsers;
using Lucene.Net.Search;

namespace Ledict.ConditionExtract.BLL
{
    /// <summary>
    /// lucence查询方法
    /// </summary>
    public class LuceneSearch
    {
        private readonly IndexSearcher _search;
        private readonly IndexSearcher _searchNew;

        public LuceneSearch()
        {
            //共享模式
            if (!string.IsNullOrEmpty(ConfigHelper.AppSettings("LuceneSearchType")) && ConfigHelper.AppSettings("LuceneSearchType").ToUpper() == "SHARE")
            {
                //连接远程服务器
                string result = Convert.ToString(WNetConnectionHelper.WNetAddConnection(ConfigHelper.AppSettings("user"), ConfigHelper.AppSettings("password"), ConfigHelper.AppSettings("share_url"), null));
            }

            string indexPath = ConfigHelper.AppSettings("luceneRoot");


            LdIndexReader ldReader = LdIndexReader.GetInstance();
            IndexReader indexReader = ldReader.GetIndexReader(indexPath); //把刚才建立的索引取出来
            _search = new IndexSearcher(indexReader);

            //要素分析使用
            //string indexPathNew = ConfigHelper.AppSettings("luceneRootNew");


            //LdIndexReader ldReaderNew = LdIndexReader.GetInstance();
            //IndexReader indexReaderNew = ldReaderNew.GetIndexReader(indexPathNew); //把刚才建立的索引取出来
            //_searchNew = new IndexSearcher(indexReaderNew);

            //uint n = WNetConnectionHelper.WNetCancelConnection("//192.168.1.160//xurenna", 1, true);//关闭160链接
        }

        /// <summary>
        /// 查询lucene中的目标文本（分页）
        /// </summary>
        /// <param name="conditon">查询条件</param>
        /// <param name="pag">第几页</param>
        /// <param name="perPage">每页几条</param>
        /// <returns>返回分页结果</returns>
        public DataTable GetDataSource(DataSourceCondition conditon, int pag, int perPage)
        {
            try
            {
                BooleanQuery query = new BooleanQuery();

                AddFuzzyQuery("AllParentID", conditon.HeadwordId, Occur.MUST, query);
                AddTermQuery("JudicialProcedureId", conditon.JudicialProcedureId, Occur.MUST, query);
                AddTermQuery("PropertyId", conditon.PropertyId, Occur.MUST, query);
                AddTermQuery("ParagraphTypeId", conditon.ParagraphType, Occur.MUST, query);
                if (conditon.CaseIdStart != "" && conditon.CaseIdEnd != "")
                    AddTermRangeQuery("CaseId", conditon.CaseIdStart, conditon.CaseIdEnd, Occur.MUST, query);
                AddTermQuery("ParagraphTypeId", conditon.ParagraphType, Occur.MUST, query);
                //  AddQueryParser("Sentence", "争议焦点", Occur.MUST, query);

                //排序
                Sort fieldSort = new Sort(new SortField("SentenceTime", SortField.STRING, true));

                TopDocs topdocs = _search.Search(query, null, pag * perPage, fieldSort);
                ScoreDoc[] scoreDocs = topdocs.ScoreDocs; // 搜索返回的结果集合

                //查询起始记录位置
                int begin = perPage * (pag - 1);

                //查询终止记录位置
                int end = Math.Min(begin + perPage, scoreDocs.Length);
                DataTable dt = new DataTable();
                dt.Columns.Add("Id");
                dt.Columns.Add("CaseId");
                dt.Columns.Add("ParagraphTypeId");
                dt.Columns.Add("ParagraphText");
                dt.Columns.Add("FieldValue");

                #region MyRegion
                ////////////////////////////////////////测试/////////////////////////////////////////
                //DataRow dr = dt.NewRow();
                //dr[0] = "1";
                //dr[1] = "26159951";
                //dr[2] = "150";
                //dr[3] = @"本院认为，被告人王某某以非法占有为目的，伙同他人使用伪造的信用卡进行诈骗，数额较大，其行为已构成信用卡诈骗罪，依法应予惩处。";
                //dr[4] = "王某某";
                //dt.Rows.Add(dr);
                //dr = dt.NewRow();
                //dr[0] = "2";
                //dr[1] = "1955739";
                //dr[2] = "150";
                //dr[3] = "被告人×××因邻里琐事与被害人倪××发生争执后，故意伤害被害人倪××的身体，致被害人倪××轻伤，其行为已构成故意伤害罪，公诉机关指控的事实及罪名成立，本院予以支持。";
                //dr[4] = "xxx";
                //dt.Rows.Add(dr);
                //dr = dt.NewRow();
                //dr[0] = "3";
                //dr[1] = "1943676";
                //dr[2] = "150";
                //dr[3] = "被告人×××因家庭琐事与他人发生争执后，故意非法损害他人身体健康，致人轻伤二级，其行为已触犯我国刑法，构成故意伤害罪。";
                //dr[4] = "xxx";
                //dt.Rows.Add(dr);
                //dr = dt.NewRow();
                //dr[0] = "4";
                //dr[1] = "1907785";
                //dr[2] = "150";
                //dr[3] = "因琐事两家发生争执，在争执中，被告人×××致人成重伤，其行为已构成故意伤害罪，依法应予惩处。";
                //dr[4] = "xxx";
                //dt.Rows.Add(dr);
                //////////////////////////////////////////////////////////////////////////////////// 
                #endregion
                for (int i = begin; i < end; i++)
                {
                    Document doc = _search.Doc(scoreDocs[i].Doc);
                    DataRow dr = dt.NewRow();
                    dr[0] = doc.Get("SentenceId");
                    dr[1] = doc.Get("CaseId");
                    dr[2] = doc.Get("ParagraphTypeId");
                    dr[3] = doc.Get("Sentence");
                    dr[4] = doc.Get("FieldValue");
                    dt.Rows.Add(dr);
                }

                return dt;
            }
            catch (Exception ex)
            {
                Log.ErrorLog(ex.Message);
                throw;
            }


        }


        /// <summary>
        /// 查询lucene中的目标文本（分页）
        /// </summary>
        /// <param name="conditon">查询条件</param>
        /// <param name="pag">第几页</param>
        /// <param name="perPage">每页几条</param>
        /// <returns>返回分页结果</returns>
        public DataTable GetDataSourceNew(DataSourceCondition conditon, int pag, int perPage)
        {
            try
            {            

                BooleanQuery query = new BooleanQuery();

                AddFuzzyQuery("AllParentID", conditon.HeadwordId, Occur.MUST, query);
                AddTermQuery("JudicialProcedureId", conditon.JudicialProcedureId, Occur.MUST, query);
                AddTermQuery("ParagraphTypeId", conditon.ParagraphType, Occur.MUST, query);
                AddTermQuery("PropertyId", conditon.PropertyId, Occur.MUST, query);
                AddTermQuery("CourtId", conditon.Court, Occur.MUST, query);
                //排序
                Sort fieldSort = new Sort(new SortField("SentenceTime", SortField.STRING, true));

                TopDocs topdocs = _searchNew.Search(query, null, pag * perPage, fieldSort);
                ScoreDoc[] scoreDocs = topdocs.ScoreDocs; // 搜索返回的结果集合

                //查询起始记录位置
                int begin = perPage * (pag - 1);

                //查询终止记录位置
                int end = Math.Min(begin + perPage, scoreDocs.Length);
                DataTable dt = new DataTable();
                dt.Columns.Add("Id");
                dt.Columns.Add("CaseId");
                dt.Columns.Add("ParagraphTypeId");
                dt.Columns.Add("ParagraphText");
                dt.Columns.Add("PropertyId");
                dt.Columns.Add("JudicialProcedureId");
                dt.Columns.Add("CourtId");
                dt.Columns.Add("ParagraphId");

                for (int i = begin; i < end; i++)
                {
                    Document doc = _searchNew.Doc(scoreDocs[i].Doc);
                    DataRow dr = dt.NewRow();
                    dr[0] = doc.Get("SentenceId");
                    dr[1] = doc.Get("CaseId");
                    dr[2] = doc.Get("ParagraphTypeId");
                    dr[3] = doc.Get("Sentence");
                    dr[4] = doc.Get("PropertyId");
                    dr[5] = doc.Get("JudicialProcedureId");
                    dr[6] = doc.Get("CourtId");
                    dr[7] = doc.Get("ParagraphId");

                    dt.Rows.Add(dr);
                }

                return dt;
            }
            catch (Exception ex)
            {
                Log.ErrorLog(ex.Message);
                throw;
            }


        }


        /// <summary>
        /// 统计lucene中有目标文本的数量
        /// </summary>
        /// <param name="conditon">条件</param>
        /// <returns></returns>
        public int GetDataSourceCount(DataSourceCondition conditon)
        {
            try
            {
                BooleanQuery query = new BooleanQuery();
                AddFuzzyQuery("AllParentID", conditon.HeadwordId, Occur.MUST, query);
                AddTermQuery("JudicialProcedureId", conditon.JudicialProcedureId, Occur.MUST, query);
                if (!string.IsNullOrEmpty(conditon.PropertyId))
                {
                    AddTermQuery("PropertyId", conditon.PropertyId, Occur.MUST, query);
                }
                AddTermQuery("ParagraphTypeId", conditon.ParagraphType, Occur.MUST, query);
                if (!string.IsNullOrEmpty(conditon.CaseIdStart) && !string.IsNullOrEmpty(conditon.CaseIdEnd))
                {
                    AddTermRangeQuery("CaseId", conditon.CaseIdStart, conditon.CaseIdEnd, Occur.MUST, query);
                }
                TopDocs topdocs = _search.Search(query, 1);
                int totalCount = topdocs.TotalHits;
                return totalCount;
            }
            catch (Exception ex)
            {
                Log.ErrorLog(ex.Message);
                return -1;
            }

        }

        /// <summary>
        /// 统计lucene中有目标文本的数量
        /// </summary>
        /// <param name="conditon">条件</param>
        /// <returns></returns>
        public int GetDataSourceCountNew(DataSourceCondition conditon)
        {
            try
            {              
                BooleanQuery query = new BooleanQuery();
                AddFuzzyQuery("AllParentID", conditon.HeadwordId, Occur.MUST, query);
                AddTermQuery("JudicialProcedureId", conditon.JudicialProcedureId, Occur.MUST, query);
                if (!string.IsNullOrEmpty(conditon.PropertyId))
                {
                    AddTermQuery("PropertyId", conditon.PropertyId, Occur.MUST, query);
                }
                if (!string.IsNullOrEmpty(conditon.Court))
                {
                    AddTermQuery("CourtId", conditon.Court, Occur.MUST, query);
                }
                AddTermQuery("ParagraphTypeId", conditon.ParagraphType, Occur.MUST, query);
                if (!string.IsNullOrEmpty(conditon.CaseIdStart) && !string.IsNullOrEmpty(conditon.CaseIdEnd))
                {
                    AddTermRangeQuery("CaseId", conditon.CaseIdStart, conditon.CaseIdEnd, Occur.MUST, query);
                }
                TopDocs topdocs = _searchNew.Search(query, 1);
                int totalCount = topdocs.TotalHits;
                return totalCount;
            }
            catch (Exception ex)
            {
                Log.ErrorLog(ex.Message);
                return -1;
            }

        }

        #region  各种lucene查询方法
        /// <summary>
        /// 普通查询
        /// </summary>
        /// <param name="whereName"></param>
        /// <param name="whereValue"></param>
        /// <param name="occur"></param>
        /// <param name="query"></param>
        private void AddTermQuery(string whereName, string whereValue, Lucene.Net.Search.Occur occur, BooleanQuery query)
        {

            whereValue = whereValue.Trim();
            if (!String.IsNullOrEmpty(whereValue) || occur == Occur.MUST_NOT)
            {
                Term term = new Term(whereName, whereValue);
                Query termquery = new TermQuery(term);
                query.Add(termquery, occur);
            }
        }
        /// <summary>
        /// 分词模糊查询
        /// </summary>
        /// <param name="whereName"></param>
        /// <param name="whereValue"></param>
        /// <param name="occur"></param>
        /// <param name="query"></param>
        private void AddQueryParser(string whereName, string whereValue, Lucene.Net.Search.Occur occur, BooleanQuery query)
        {

            whereValue = new System.Text.RegularExpressions.Regex("[\\s]+").Replace(whereValue, " ");
            if (!String.IsNullOrEmpty(whereValue))
            {
                BooleanQuery queryChild = new BooleanQuery();
                string[] queryArr = whereValue.Split(new char[] { ',', ' ', '，' });
                foreach (string str in queryArr)
                {
                    if (!String.IsNullOrEmpty(str))
                    {

                        if (str.Length == 1)
                        {
                            Term termwildcard = new Term(whereName, "*" + str + "*");//模糊查询有问题
                            Query wildcardquery = new WildcardQuery(termwildcard);
                            queryChild.Add(wildcardquery, Occur.MUST);
                        }
                        else
                        {   //非法字符
                            CJKAnalyzer analyzer = new CJKAnalyzer(Lucene.Net.Util.Version.LUCENE_30);
                            QueryParser WhereNameparser = new QueryParser(Lucene.Net.Util.Version.LUCENE_30, whereName, analyzer);
                            Query WhereNamequery = WhereNameparser.Parse(str);
                            queryChild.Add(WhereNamequery, Occur.MUST);
                        }
                    }
                }
                query.Add(queryChild, occur);
            }
        }


        /// <summary>
        /// 时间查询
        /// </summary>
        /// <param name="whereName"></param>
        /// <param name="whereValue1"></param>
        /// <param name="whereValue2"></param>
        /// <param name="occur"></param>
        /// <param name="query"></param>
        private void AddTermRangeQuery(string whereName, string whereValue1, string whereValue2, Lucene.Net.Search.Occur occur, BooleanQuery query)
        {
            if (!String.IsNullOrEmpty(whereValue1))
            {
                TermRangeQuery Timequery = new TermRangeQuery(whereName, whereValue1, whereValue2, true, true);
                query.Add(Timequery, occur);

            }
        }
        /// <summary>
        /// 通配符查询
        /// </summary>
        /// <param name="whereName"></param>
        /// <param name="whereValue"></param>
        /// <param name="occur"></param>
        /// <param name="query"></param>
        private void AddWildcardQuery(string whereName, string whereValue, Lucene.Net.Search.Occur occur, BooleanQuery query)
        {
            whereValue = whereValue.Trim();
            if (!String.IsNullOrEmpty(whereValue))
            {
                Term termwildcard = new Term(whereName, "*" + whereValue + "*");
                Query wildcardquery = new WildcardQuery(termwildcard);
                query.Add(wildcardquery, occur);

            }
        }

        /// <summary>
        /// 前缀匹配
        /// </summary>
        /// <param name="whereName"></param>
        /// <param name="whereValue"></param>
        /// <param name="occur"></param>
        /// <param name="query"></param>
        private void AddFuzzyQuery(string whereName, string whereValue, Lucene.Net.Search.Occur occur, BooleanQuery query)
        {
            if (!String.IsNullOrEmpty(whereValue))
            {
                Term termwildcard = new Term(whereName, whereValue + "*");
                Query wildcardquery = new WildcardQuery(termwildcard);
                query.Add(wildcardquery, occur);

            }
        }

        #endregion
    }
}
